package com.army.modules.batch.job;

import com.army.common.properties.FileProperties;
import com.army.modules.host.entity.HostWater;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.job.builder.FlowBuilder;
import org.springframework.batch.core.job.flow.Flow;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.database.JdbcCursorItemReader;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.transform.DelimitedLineAggregator;
import org.springframework.batch.item.file.transform.FormatterLineAggregator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;

import javax.sql.DataSource;

@Slf4j
@Configuration
@AllArgsConstructor
public class DataTofile {
    private final DataSource dataSource;
    private final JobLauncher jobLauncher;
    private final FileProperties fileProperties;
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;
    private final DataToFileJobListener dataToFileJobListener;

    /**
     * 接收任务批量写文件
     *
     * @param jobParameters jobParameters
     */
    public void run(JobParameters jobParameters) throws Exception {
        String batchNo = jobParameters.getString("batchNo");
        try {
            jobLauncher.run(writeFileJob(), jobParameters);
        }  catch (Exception e) {
            log.error("代发批次号[{}]执行批量写文件任务异常：", batchNo, e);
            throw e;
        }
    }

    /**
     * 初始化任务
     *
     * @return Job
     * @throws Exception Exception
     */
    @Bean
    public Job writeFileJob() throws Exception {
        return jobBuilderFactory.get("writeFileJob")
                .incrementer(new RunIdIncrementer())
                .start(writeFileFlow())
                .end()
                .listener(dataToFileJobListener)
                .build();
    }

    /**
     * 初始化任务流
     *
     * @return Flow
     * @throws Exception Exception
     */
    @Bean
    public Flow writeFileFlow() throws Exception {
        return new FlowBuilder<Flow>("writeFileFlow")
                .start(writeFileStep())
                .build();
    }

    /**
     * 初始化任务步骤
     *
     * @return Step
     * @throws Exception Exception
     */
    @Bean
    public Step writeFileStep() throws Exception {
        return stepBuilderFactory.get("writeFileStep")
                .<HostWater, HostWater>chunk(100)
                .reader(writeFileItemReader())
                .writer(writeFileItemWriter("", "",""))
                .build();
    }
    /**
     * 初始化批处理读取器
     * @return JdbcCursorItemReader<ABusiness>
     */
    @Bean(destroyMethod = "")
    @StepScope
    public JdbcCursorItemReader<HostWater> writeFileItemReader() {
        JdbcCursorItemReader<HostWater> reader = new JdbcCursorItemReader<>();
        try {
            String sql = "select h.* from host_water h,a_business a\n" +
                    "where h.global_no=a.sys_water_no and a.send_status='00' and a.`status`='01' ";
            reader.setDataSource(dataSource);
            reader.setSql(sql);
            //实体赋值
            reader.setRowMapper((resultSet, rowNum) -> {
                HostWater hostWater = new HostWater();
                hostWater.setGlobalNo(resultSet.getString("global_no"));
                hostWater.setBorrowAcct(resultSet.getString("borrow_acct"));
                hostWater.setLoansAcct(resultSet.getString("loans_acct"));
                hostWater.setTransDate(resultSet.getString("trans_date"));
                hostWater.setTransTime(resultSet.getString("trans_time"));
                hostWater.setTransResult(resultSet.getString("trans_result"));
                return hostWater;
            });
            reader.afterPropertiesSet();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return reader;
    }

    /**
     * 初始化批处理写入器
     * @return FlatFileItemWriter<ABusiness>
     * @throws Exception Exception
     */
    @Bean
    @StepScope
    public FlatFileItemWriter<HostWater> writeFileItemWriter(
            @Value("#{jobParameters['fileName']}") String fileName,
            @Value("#{jobParameters['totalCnt']}") String totalCnt,
            @Value("#{jobParameters['totalAmt']}") String totalAmt
    ) throws Exception {
        DelimitedLineAggregator<HostWater> dl = new DelimitedLineAggregator<>();
        String delimiter = "";
        dl.setDelimiter(delimiter);
        FormatterLineAggregator<HostWater> fa = new FormatterLineAggregator<>();
        fa.setFormat("%*-32s%*-16s%*-16s%*-8s%*-8s%*-6s");
        dl.setFieldExtractor(hostWater -> {
            String[] values = new String[6];
            values[0] =format(hostWater.getGlobalNo(),32);
            values[1] = format(hostWater.getBorrowAcct(),16);
            values[2] = format(hostWater.getLoansAcct(),16);
            values[3] = format(hostWater.getTransDate(),8);
            values[4] = format(hostWater.getTransTime(),8);
            values[5] = format(hostWater.getTransResult(),6);
            return values;
        });
        FlatFileItemWriter<HostWater> writer = new FlatFileItemWriter<>();
        // 从数据库表获取生成文件路径
        writer.setResource(new FileSystemResource(fileName));
        log.info("生成报盘文件的文件名：[{}]", fileName);
        writer.setLineAggregator(dl);
        writer.setEncoding("UTF-8");
        writer.afterPropertiesSet();
        writer.setLineSeparator("\n");
        writer.setHeaderCallback(header -> header.write(format(totalCnt,4)+format(totalAmt,18)));
        return writer;
    }

    public static String format(String s,int length){
       if (s.length()<=length){
           StringBuilder builder = new StringBuilder(s);
           for (int i=0;i<length-s.length();i++){
               builder.append("*");
           }
           return builder.toString();
       }else {
           return s.substring(0,length);
       }
    }
}
